#pragma once
#include<iostream>
#include<pthread.h>
#include<vector>
#include <semaphore.h>
template<class T>
class Ringqueue
{
public:
    //P- V+
    void P(sem_t &sem)  //传入信号量得传引用
    {
        sem_wait(&sem); //--
        
    }

    void V(sem_t &sem)
    {
        sem_post(&sem);//++
    }
    void Lock(pthread_mutex_t &mutex)
    {
        pthread_mutex_lock(&mutex);
    }
    void Unlock(pthread_mutex_t &mutex)
    {
        pthread_mutex_unlock(&mutex);
    }
    Ringqueue(int num)
        :_rq(num)
        ,_num(num)
        ,_Pindex(0)
        ,_Cindex(0)
    {
        pthread_mutex_init(&_Pmutex,nullptr);
        pthread_mutex_init(&_Cmutex,nullptr);
        sem_init(&_Psem,0,_num); //第二个参数传入0表示线程间共享
        sem_init(&_Csem,0,0);
    }
    ~Ringqueue()
    {
        sem_destroy(&_Psem);
        sem_destroy(&_Csem);

        pthread_mutex_destroy(&_Pmutex);
        pthread_mutex_destroy(&_Cmutex);
    }
    //生产
    void Push(const T& task)
    {
        P(_Psem); //信号量是原子的
        Lock(_Pmutex);
        _rq[_Pindex++]=task;
        _Pindex%=_num; //
        Unlock(_Pmutex);
        V(_Csem);
    }
    //
   
    T Pop()
    {
        P(_Csem);
        Lock(_Cmutex);
        T out=_rq[_Cindex++];
        _Cindex%=_num; 
        Unlock(_Cmutex);
        V(_Psem);
        return out;
    }


private:
    std::vector<T> _rq;
    int _Pindex;
    int _Cindex;
    int _num;
    pthread_mutex_t _Pmutex; //生产者和消费者下标临界资源不同，需要两把锁
    pthread_mutex_t _Cmutex;
    sem_t _Psem;
    sem_t _Csem;
    
};